package com.xbongbong.pro.statistics.help;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.XbbConstant;
import com.xbongbong.paas.enums.AggTypeEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.bi.commons.pojo.AggFieldPojo;
import com.xbongbong.pro.bi.commons.pojo.vo.GroupSqlVO;
import com.xbongbong.pro.constant.SymbolConstant;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.pojo.ChartFieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.FieldAttrPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 描述信息
 *
 * @ClassName DisplayHelper
 * @Author 梁鲁江
 * 创建时间 2022/9/19 15:58
 * 修改时间  2022/9/19 15:58
 **/
@Component
public class DisplayHelper {
    /**
     * 处理表头Field关键信息
     * @param chartType
     * @param fieldAttrPojo
     * @return
     */
    public JSONObject setHeadField(Integer chartType, ChartFieldAttrPojo fieldAttrPojo) {
        Integer fieldType = fieldAttrPojo.getFieldType();
        String attr = fieldAttrPojo.getAttr();
        JSONObject headName = new JSONObject();
        String label = fieldAttrPojo.getLabel();
        String labelName = fieldAttrPojo.getLabelName();
        String attrName = fieldAttrPojo.getAttrName();
        if(StringUtil.isEmpty(label) && StringUtil.isEmpty(labelName)){
            labelName = attrName;
        }
        if (Objects.equals(chartType, ChartTypeEnum.PK_CUSTOM.getCode())) {
            // 自定义pk
            headName.put("name", attrName);
        } else if (fieldAttrPojo.getAggType() != null) {
            // 查询表，汇总字段也会加到表头字段中，所以查询汇总方式
            AggTypeEnum aggTypeEnum = AggTypeEnum.getByAlias(fieldAttrPojo.getAggType());
            if (Objects.equals(FieldTypeEnum.SUB_FORM.getType(), fieldType)) {
                if (Objects.equals(labelName, label)) {
                    headName.put("name", attrName + "(" + aggTypeEnum.getName() + ")");
                } else {
                    headName.put("name", labelName + "(" + aggTypeEnum.getName() + ")");
                }
            } else {
                if (Objects.equals(labelName, label)) {
                    String temp = Arrays.asList(label.split("--")).get(0);
                    if (StringUtil.isNotEmpty(attrName)) {
                        temp = temp + "--" + attrName;
                    }
                    headName.put("name", temp + "(" + aggTypeEnum.getName() + ")");
                } else {
                    headName.put("name", labelName + "(" + aggTypeEnum.getName() + ")");
                }
            }
        } else {
            if (Objects.equals(FieldTypeEnum.SUB_FORM.getType(), fieldType)) {
                if (Objects.equals(labelName, label)) {
                    String temp = Arrays.asList(label.split("--")).get(0);
                    if (StringUtil.isNotEmpty(attrName)) {
                        temp = temp + "--" + attrName;
                    }
                    headName.put("name", temp);
                } else {
                    headName.put("name", labelName);
                }
            } else {
                if (Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(), fieldType)) {
                    headName.put("name", Arrays.asList(label.split("--")).get(0));
                } else {
                    if (Objects.equals(labelName, label)) {
                        String temp = Arrays.asList(label.split("--")).get(0);
                        if (StringUtil.isNotEmpty(attrName)) {
                            temp = temp + "--" + attrName;
                        }
                        headName.put("name", temp);
                    } else {
                        headName.put("name", labelName);
                    }
                }
            }
        }
        Long formId = fieldAttrPojo.getFormId();
        headName.put("frozeKey", formId + attr);
        headName.put("key", attr + "&" + fieldAttrPojo.getFieldType());
        headName.put("formId", formId);
        headName.put("fieldType", fieldAttrPojo.getFieldType());
        headName.put("columnFlag", fieldAttrPojo.getColumnFlag());
        headName.put("originAttr", fieldAttrPojo.getOriginalAttr());
        headName.put("attr", attr);
        headName.put("bgColor", fieldAttrPojo.getBgColor());
        headName.put(StringConstant.BUSINESS_TYPE, fieldAttrPojo.getBusinessType());
        if (fieldAttrPojo.getDateGroupType() != null) {
            headName.put("dateGroupType", fieldAttrPojo.getDateGroupType());
        }
        return headName;
    }

    /**
     * 设置子表单表头
     * @param fieldAttrPojo  
     * @param headName  表头需要的字段详情
     */
    public  void subFieldItems(FieldAttrPojo fieldAttrPojo, JSONObject headName) {
        SubFormPoJo subFormPoJo = fieldAttrPojo.getSubForm();
        String str = JSONArray.toJSONString(subFormPoJo.getItems(), SerializerFeature.DisableCircularReferenceDetect);
        List<FieldAttrPojo> subFormAttrs = JSONArray.parseArray(str, FieldAttrPojo.class);
        List<JSONObject> subFormItems = new ArrayList<>();
        subFormAttrs.forEach(field -> {
            String attr = field.getAttr();
            JSONObject subFormObj = new JSONObject();
            String parentStr;
            String childStr;
            if (Objects.equals(fieldAttrPojo.getLabelName(), fieldAttrPojo.getLabel())) {
                parentStr = fieldAttrPojo.getAttrName();
            } else {
                parentStr = fieldAttrPojo.getLabelName();
            }
            if (Objects.equals(field.getLabelName(), field.getLabel())) {
                childStr = field.getAttrName();
            } else {
                childStr = field.getLabelName();
            }
            AggTypeEnum aggTypeEnum = AggTypeEnum.getByAlias(field.getAggType());
            if (Objects.isNull(field.getAggType())) {
                subFormObj.put("name", parentStr +  SymbolConstant.POINT_ENGLISH   + childStr);
            } else {
                subFormObj.put("name", parentStr +  SymbolConstant.POINT_ENGLISH   + childStr + "(" + aggTypeEnum.getName() + ")");
            }
            subFormObj.put("key", attr + "&" + field.getFieldType());
            subFormObj.put("formId", fieldAttrPojo.getFormId());
            subFormObj.put("fieldType", field.getFieldType());
            subFormObj.put("bgColor", field.getBgColor());
            subFormObj.put("fieldAttrPojo", field);
            subFormItems.add(subFormObj);
        });
        headName.put("items", subFormItems);
    }
    
    /**
     * 获取排序
     *
     * @param chartEntity
     * @param sortStatisticsMap
     * @return
     */
    public Map<String, String> getSortMap(ChartEntity chartEntity, Map<String, String> sortStatisticsMap) {
        Map<String, String> sortMap = sortStatisticsMap;
        if (Objects.isNull(sortMap)) {
            JSONObject explains = chartEntity.getExplains();
            if (explains != null) {
                JSONObject jsonObject = explains.getJSONObject("sortMap");
                if (jsonObject != null) {
                    Map<String, Object> sortMap1 = jsonObject.getInnerMap();
                    sortMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for (Map.Entry<String, Object> stringObjectEntry : sortMap1.entrySet()) {
                        sortMap.put(stringObjectEntry.getKey(), stringObjectEntry.getValue().toString());
                    }
                }
            }
        }
        return sortMap;
    }
    public String getAggSortField(Map<String, String> sortFieldMap, GroupSqlVO groupSqlVO) {
        List<String> sortFieldList = new ArrayList<>();
        if(Objects.isNull(sortFieldMap) || sortFieldMap.isEmpty()){
            return "";
        }

        //子查询SQL： 内层只排分组字段（因为有limit的存在，保证对应的分组可以被查出来），外层排分组+汇总字段
        List<String> computeStrList = new ArrayList<>();
        List<String> subOrderSqlOfCountList = new ArrayList<>();
        boolean subSqlFlag = CollectionsUtil.isNotEmpty(groupSqlVO.getSubQuerySqlOfCountList());
        if(subSqlFlag){
            computeStrList = groupSqlVO.getSubQuerySqlOfCountList().stream().map(str ->
            {
                String[] split = str.split(XbbConstant.AS);
                return split.length == BasicConstant.TWO ? split[BasicConstant.ONE].trim() : str;
            }).collect(Collectors.toList());
        }

        for (String s : sortFieldMap.keySet()) {
            String value = sortFieldMap.get(s);
            if (Objects.equals("asc", value.trim()) || Objects.equals("desc", value.trim()) ||  Objects.equals("default", value.trim())){
                continue;
            }
            if(subSqlFlag){
                //子查询：外层排所有，内层排除了包含count的计算字段
                if(!computeStrList.contains(s)){
                    sortFieldList.add(value);
                }
                String orderSql = dealOrderFiledName(groupSqlVO,s,value);
                subOrderSqlOfCountList.add(orderSql);
            }else{
                //普通查询直接添加
                sortFieldList.add(value);
            }
        }
        groupSqlVO.setSubOrderSqlOfCount(String.join(XbbConstant.SQL_COMMA,subOrderSqlOfCountList));
        return String.join(XbbConstant.SQL_COMMA,sortFieldList);
    }

    private String dealOrderFiledName(GroupSqlVO groupSqlVO, String key, String value) {
        //子查询sql拆分后，外层只能用别名进行排序
        //整体做法就是 取字段名  取排序key  最后拼接

        //计数字段不解析,截取后返回 count() AS count_1 acs
        if(AggTypeEnum.COUNT.getAlias().equals(key)){
            return value.split(XbbConstant.AS)[1];
        }

        //普通汇总字段可能会转一层，如num_1、求和 会转成sum_1，所以在外层排序的时候要拿sum_1，即aggFieldMap中的key
        //非普通汇总字段如计算字段，那么内层attr跟外层key是相同的
        Map<String, AggFieldPojo> aggFieldMap = groupSqlVO.getAggFieldMap();
        for (Map.Entry<String, AggFieldPojo> aggFieldPojoEntry : aggFieldMap.entrySet()) {
            AggFieldPojo aggFieldPojo = aggFieldPojoEntry.getValue();
            if(key.equals(aggFieldPojo.getAttr())){
                key = aggFieldPojoEntry.getKey();
                break;
            }
        }

        //判断是否需要驼峰转下划线
        if(!key.contains(XbbConstant.SEPARATOR)){
            key = StringUtil.getDataBaseString(key);
        }
        String orderKey = value.contains(StringConstant.SORT_ASC_TAG) ? StringConstant.SORT_ASC_TAG : StringConstant.SORT_DESC_TAG;
        return key + XbbConstant.SPACE + orderKey;
    }

    public String getDsAggSortField(Map<String, String> sortFieldMap,GroupSqlVO groupSqlVO) {
        //排序字段分为三种情况
        //1. 分组字段 \ 计算字段 直接使用 attr + 排序标志
        //2. 汇总字段 attr 跟 数据库别名可能不一致，因此在aggHelper.addValuesField中重新覆盖
        List<String> sortFieldAlisaList = new ArrayList<>();
        if(Objects.isNull(sortFieldMap) || sortFieldMap.isEmpty()){
            return "";
        }

        //子查询SQL: 外层排所有、内层排 除了包含count函数的所有字段
        List<String> computeStrList = new ArrayList<>();
        List<String> subOrderSqlOfCountList = new ArrayList<>();
        boolean subSqlFlag = CollectionsUtil.isNotEmpty(groupSqlVO.getSubQuerySqlOfCountList());
        if(subSqlFlag){
            computeStrList = groupSqlVO.getSubQuerySqlOfCountList().stream().map(str ->
            {
                String[] split = str.split(XbbConstant.AS);
                return split.length == BasicConstant.TWO ? split[BasicConstant.ONE].trim() : str;
            }).collect(Collectors.toList());
        }
        for (String attr : sortFieldMap.keySet()) {
            String value = sortFieldMap.get(attr);
            String orderStr;
            if(Objects.equals("asc", value.trim()) || Objects.equals("desc", value.trim()) ||  Objects.equals("default", value.trim())){
                orderStr = attr + XbbConstant.SPACE +  value;
            }else{
                orderStr = value;
            }
            if(subSqlFlag){
                subOrderSqlOfCountList.add(orderStr);
                if(!computeStrList.contains(attr)){
                    sortFieldAlisaList.add(orderStr);
                }
            }else{
                sortFieldAlisaList.add(orderStr);
            }
        }
        groupSqlVO.setSubOrderSqlOfCount(String.join(XbbConstant.SQL_COMMA,subOrderSqlOfCountList));
        return String.join(XbbConstant.SQL_COMMA,sortFieldAlisaList);
    }

    /**
     * 清除排序中的辅助信息，用于统计
     *
     * @param chartEntity
     * @param sortStatisticsMap
     * @return
     */
    public Map<String, String> getAggSortMap(ChartEntity chartEntity, Map<String, String> sortStatisticsMap,List<String> sortFieldOrder) {
        Map<String, String> sortMap = getSortMap(chartEntity, sortStatisticsMap);
        //BI-Q3 统计表选择小计时，不进行排序
        if(Objects.equals(ChartTypeEnum.DATA_STATISTICS_TABLE.getCode(),chartEntity.getChartType()) && Objects.equals(chartEntity.getSum(),0)){
            sortMap = null;
        }
        Map<String, String> sortFieldMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (sortMap != null && !sortMap.isEmpty()) {
            //sortMap不为空，那么sortFieldOrder也不为空
            //固定排序字段的顺序
            if(Objects.isNull(sortFieldOrder)){
                for (Map.Entry<String, String> stringStringEntry : sortMap.entrySet()) {
                    String value = stringStringEntry.getValue();
                    //前端从升序或者降序切回默认值的时候会传default
                    if(Objects.equals("default",value)){
                        continue;
                    }
                    String[] keyArray = stringStringEntry.getKey().split("&");
                    String attr = keyArray[0];
                    sortFieldMap.put(attr, value);
                }
            }else{
                for (String sortField : sortFieldOrder) {
                    String value = sortMap.get(sortField);
                    //前端从升序或者降序切回默认值的时候会传default
                    if(Objects.equals("default",value)){
                        continue;
                    }
                    String[] keyArray = sortField.split("&");
                    String attr = keyArray[0];
                    sortFieldMap.put(attr, value);
                }
            }
        }
        return sortFieldMap;
    }

    /**
     * 处理汇总
     *
     * @param summaryAttrList
     * @param tableHead
     * @param parseAttrMap
     * @param summaryAttrMap
     * @param isSingle
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2021/11/22 13:51
     * @version 1.0
     */
    public void handleSummary(List<FieldAttrPojo> summaryAttrList, JSONArray tableHead, Map<JSONObject, FieldAttrPojo> parseAttrMap, Map<String, FieldAttrPojo> summaryAttrMap, boolean isSingle) {
        if (summaryAttrList != null) {
            for (FieldAttrPojo fieldAttrPojo : summaryAttrList) {
                String labelName = fieldAttrPojo.getLabelName();
                Long formId = fieldAttrPojo.getFormId();
                String attr = fieldAttrPojo.getAttr();
                Integer fieldType = fieldAttrPojo.getFieldType();
                AggTypeEnum aggTypeEnum = AggTypeEnum.getByAlias(fieldAttrPojo.getAggType());
                JSONObject headName = new JSONObject();
                headName.put("name", labelName + "(" + aggTypeEnum.getName() + ")");
                String key =  attr + "&" + fieldType;
                headName.put("key", key);
                headName.put("formId", formId);
                headName.put("fieldType", fieldType);
                headName.put("summaryAttr", 1);
                tableHead.add(headName);
                parseAttrMap.put(headName, fieldAttrPojo);
                if (summaryAttrMap != null) {
                    summaryAttrMap.put(attr + "&" + fieldType, fieldAttrPojo);
                }
            }
        }
    }
}
